home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dc1 / block.c < prev    next >
C/C++ Source or Header  |  1997-09-09  |  10KB  |  428 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6.  
  7. /*
  8.  *  BLOCK.C
  9.  */
  10.  
  11. #include "defs.h"
  12.  
  13. Prototype BlockStmt *CurGen;
  14. Prototype short BlockCost;
  15.  
  16. BlockStmt *CurBlock;
  17. BlockStmt *CurGen;
  18. Var *TopVarBase;    /*  list of top-level variables */
  19.  
  20. short    BlockCost;    /*  how costly will operations be time-relative */
  21.             /*  (e.g. keep loop variables in registers when */
  22.             /*  we run out!)                */
  23.  
  24. Prototype BlockStmt *BlockDown(short);
  25. Prototype BlockStmt *BlockUp(void);
  26. Prototype Var *BlockAddVar(Var *);
  27. Prototype void BlockAddStmt(Stmt *);
  28. Prototype void BlockFlagCallMade(void);
  29. Prototype long FindContinueLabel(void);
  30. Prototype long FindBreakLabel(void);
  31. Prototype void GenPush(BlockStmt *);
  32. Prototype void GenFlagCallMade(void);
  33. Prototype void GenPop(BlockStmt *);
  34. Prototype void BlockAddTop(Var *);
  35. Prototype Var *BlockRemoveDuplicateVar(long, Symbol *, Type *);
  36. Prototype int CompareTypes(long, long, Type *, Type *);
  37.  
  38. BlockStmt *
  39. BlockDown(short bid)
  40. {
  41.     BlockStmt *block = AllocTmpStructure(BlockStmt);
  42.  
  43.     SemanticLevelDown();
  44.  
  45.     block->st_Func = (void (*)(void *))GenBlock;
  46.     block->st_Tok  = TokBlock;
  47.     block->Bid = bid;
  48.     block->Parent = CurBlock;
  49.     block->Last = &block->Base;
  50.     block->LastVar = &block->VarBase;
  51.  
  52.     CurBlock = block;
  53.  
  54.     return(block);
  55. }
  56.  
  57. BlockStmt *
  58. BlockUp()
  59. {
  60.     BlockStmt *block = CurBlock;
  61.  
  62.     Assert(CurBlock);
  63.  
  64.     block->LastLexIdx = LFBase->lf_Index;
  65.  
  66.     if (block->Parent) {
  67.     if (block->Frame.Flags & FF_CALLMADE)
  68.         block->Parent->Frame.Flags |= FF_CALLMADE;
  69.     }
  70.     CurBlock = block->Parent;
  71.  
  72.     SemanticLevelUp();
  73.  
  74.     return(CurBlock);
  75. }
  76.  
  77. /*
  78.  *  static variables are added in front so they are run BEFORE any
  79.  *  lea'd dummies of them.
  80.  *
  81.  *  Returns base of list added to current block minus any variables added
  82.  *  to the top level (i.e. procedures)
  83.  */
  84.  
  85. Var *
  86. BlockAddVar(var)
  87. Var *var;
  88. {
  89.     BlockStmt *block;
  90.     Var *vnext;
  91.     Var **vbase;
  92.  
  93.     block = CurBlock;
  94.     vbase = block->LastVar;
  95.  
  96.     while (var) {
  97.     vnext = var->Next;
  98.     var->Next = NULL;
  99.  
  100.     if (var->Type->Id == TID_PROC || (var->Flags & TF_EXTERN)) {
  101.         BlockAddTop(var);
  102.     } else {
  103.         Assert(block);
  104.         if (State == SARG)
  105.         var->Flags |= VF_ARG;
  106.         *block->LastVar = var;
  107.         block->LastVar = &var->Next;
  108.     }
  109.     var = vnext;
  110.     }
  111.     return(*vbase);
  112. }
  113.  
  114. void
  115. BlockAddStmt(stmt)
  116. Stmt *stmt;
  117. {
  118.     BlockStmt *block = CurBlock;
  119.  
  120.     Assert(block);
  121.     if (stmt) {
  122.     *block->Last = stmt;
  123.     block->Last = &stmt->st_Next;
  124.     }
  125. }
  126.  
  127. void
  128. BlockFlagCallMade()
  129. {
  130.     Assert(CurBlock);
  131.     /*CurBlock->Frame.RegCantUse |= REGSCRATCH;*/
  132.     CurBlock->Frame.Flags |= FF_CALLMADE;
  133. }
  134.  
  135.  
  136. long
  137. FindContinueLabel()
  138. {
  139.     BlockStmt *block = CurBlock;
  140.  
  141.     while (block) {
  142.     switch(block->Bid) {
  143.     case BT_FOR:
  144.     case BT_WHILE:
  145.     case BT_DO:
  146.         return(block->LabelTest);
  147.     }
  148.     block = block->Parent;
  149.     }
  150.     return(0);
  151. }
  152.  
  153. long
  154. FindBreakLabel()
  155. {
  156.     BlockStmt *block = CurBlock;
  157.  
  158.     while (block) {
  159.     switch(block->Bid) {
  160.     case BT_FOR:
  161.     case BT_WHILE:
  162.     case BT_DO:
  163.     case BT_SWITCH:
  164.         return(block->LabelBreak);
  165.     }
  166.     block = block->Parent;
  167.     }
  168.     return(0);
  169. }
  170.  
  171. /*
  172.  *            Generation phase
  173.  */
  174.  
  175. void
  176. GenPush(child)
  177. BlockStmt *child;
  178. {
  179.     BlockStmt *block = CurGen;
  180.  
  181.     Assert(child);
  182.     Assert(child->Parent == block);
  183.     /* cerror(ESOFT, "Block mismatch %08lx %08lx %08lx", child, child->Parent, block); */
  184.     if (block) {
  185.     child->Frame.StackParent = block->Frame.StackParent + block->Frame.StackUsed;
  186.     } else {
  187.     ResetRegAlloc();
  188.     child->Frame.StackParent = 0;
  189.     }
  190.     child->Frame.StackUsed     = 0;
  191.     child->Frame.DownStackUsed = 0;
  192.     child->Frame.ArgsStackUsed = 0;
  193.     child->Frame.SubARegOver = 0;
  194.     child->Frame.SubDRegOver = 0;
  195.     child->Frame.CurARegOver = 0;
  196.     child->Frame.CurDRegOver = 0;
  197.  
  198.     PushStackStorage();
  199.  
  200.     /*
  201.     if (child->Frame.RegCantUse)
  202.     RegDisableRegs(child->Frame.RegCantUse);
  203.     else
  204.     RegEnableRegs();
  205.     */
  206.  
  207.     CurGen = child;
  208. }
  209.  
  210. void
  211. GenFlagCallMade()
  212. {
  213.     Assert(CurGen);
  214.     /*CurGen->Frame.RegCantUse |= REGSCRATCH;*/
  215.     if ((CurGen->Frame.Flags & FF_CALLMADE) == 0) {
  216.     RegFlagTryAgain();
  217.     CurGen->Frame.Flags |= FF_CALLMADE;
  218.     }
  219. }
  220.  
  221. /*
  222.  *  pop a frame.  Count # of registers over-allocated.
  223.  */
  224.  
  225. void
  226. GenPop(chk)
  227. BlockStmt *chk;
  228. {
  229.     BlockStmt *block;
  230.     BlockStmt *child;
  231.  
  232.     Assert(chk == CurGen);
  233.     Assert(child = CurGen);
  234.  
  235.     PopStackStorage();
  236.     if ((block = chk->Parent) != NULL) {
  237.     if (block->Frame.DownStackUsed < child->Frame.StackUsed + child->Frame.DownStackUsed)
  238.         block->Frame.DownStackUsed = child->Frame.StackUsed + child->Frame.DownStackUsed;
  239.     block->Frame.DownStackUsed = Align(block->Frame.DownStackUsed, STACK_ALIGN);
  240.  
  241.     /*
  242.      *  asm2.c, support routines call.  RegCantUse effects register
  243.      *  allocation of scratch registers.
  244.      */
  245.  
  246.     if (child->Frame.Flags & FF_CALLMADE)
  247.         block->Frame.Flags |= FF_CALLMADE;
  248.  
  249.     if (block->Frame.SubARegOver < child->Frame.CurARegOver + child->Frame.SubARegOver)
  250.         block->Frame.SubARegOver = child->Frame.CurARegOver + child->Frame.SubARegOver;
  251.     if (block->Frame.SubDRegOver < child->Frame.CurDRegOver + child->Frame.SubDRegOver)
  252.         block->Frame.SubDRegOver = child->Frame.CurDRegOver + child->Frame.SubDRegOver;
  253.     }
  254.     CurGen = block;
  255. }
  256.  
  257. /*
  258.  *  Deal with procedure declarations and possibly externs that exist
  259.  *  within
  260.  */
  261.  
  262. void
  263. BlockAddTop(var)
  264. Var *var;
  265. {
  266.     Var *first = var;
  267.  
  268.     for (;;) {
  269.     AllocExternalStorage(var->Sym, &var->var_Stor, var->Type, var->Flags);
  270.     if (var->Next == NULL)
  271.         break;
  272.     var = var->Next;
  273.     }
  274.     var->Next = TopVarBase;
  275.     TopVarBase = first;
  276. }
  277.  
  278. /*
  279.  *  This handles subroutine declarations within subroutines by bumping them up
  280.  *  to the top level, and forward declarations (i.e. an extern at top and the
  281.  *  actual variable declared later on).
  282.  */
  283.  
  284. Var *
  285. BlockRemoveDuplicateVar(storFlags, sym, type)
  286. long storFlags;
  287. Symbol *sym;
  288. Type *type;
  289. {
  290.     Var **base;
  291.     Var *var;
  292.  
  293.     if (type->Id == TID_PROC || ((storFlags & TF_AUTO) == 0 && State == SOUTSIDE)) {
  294.     base = &TopVarBase;
  295.  
  296.     while (*base && (*base)->Sym != sym)
  297.         base = &(*base)->Next;
  298.     if ((var = *base) != NULL) { 
  299.         /*
  300.          * uh oh, duplicate... extern?.  If proc auto ext
  301.          */
  302.         *base = var->Next;
  303.         var->Next = NULL;
  304.  
  305.         /*
  306.          *    If a procedure use prototype'd type.  Compare args.
  307.          *
  308.          *    If a normal declaration we have a duplicate.  However, if
  309.          *    -mu (UNIX common variables) are implemented allow a new
  310.          *    declaration to overide the old.
  311.          */
  312.  
  313.         if (type->Id != TID_PROC && (storFlags & TF_EXTERN) == 0 && (var->Flags & TF_EXTERN) == 0)
  314.         {
  315.         if (UnixCommonOpt && var->Refs == 0 && var->u.AssExp == NULL)
  316.             ;
  317.         else
  318.             yerror(var->LexIdx, EERROR_DUPLICATE_SYMBOL,
  319.                    var->Sym->Len, var->Sym->Name);
  320.         var = NULL;
  321.         } else if (type != var->Type &&
  322.                    CompareTypes(var->LexIdx, LFBase->lf_Index, type, var->Type) < 0) {
  323.         var = NULL;
  324.         }
  325.     }
  326.     } else {
  327.     Assert(CurBlock);
  328.     var = NULL;
  329.     }
  330.     return(var);
  331. }
  332.  
  333. int
  334. CompareTypes(long olexIdx, long lexIdx, Type *tn, Type *to)
  335. {
  336.     while (tn != to) {
  337.     if (tn == NULL || to == NULL)
  338.         break;
  339. /* what about TID_FLT */
  340.     switch(tn->Id) {
  341.     case TID_INT:
  342.         if (tn->Size == to->Size && ((tn->Flags ^ to->Flags) & TF_COMPAREQUALS) == 0)
  343.         return(0);
  344.             if (to->Id != TID_INT) return(-1);
  345.         break;
  346.     case TID_PTR:
  347.     case TID_ARY:
  348.         /*
  349.          *    XXX extern fubar[]; verses declaration *fubar; not checked
  350.          */
  351.             if ((to->Id != TID_PTR) && (to->Id != TID_ARY)) return(-1);
  352.         if ((tn->Id == TID_PTR && tn->SubType->Size == 0) ||
  353.             (to->Id == TID_PTR && to->SubType->Size == 0))
  354.         return(0);
  355.         tn = tn->SubType;
  356.         to = to->SubType;
  357.         continue;
  358.     case TID_PROC:
  359.             /* (ProtoOnlyOpt) ? EERROR : EWARN */
  360.             if (to->Id != TID_PROC)
  361.             {
  362.                yerror(lexIdx, EERROR_ILLEGAL_ASSIGNMENT);
  363.                return(-1);
  364.             }
  365.  
  366.         if (CompareTypes(olexIdx, lexIdx, tn->SubType, to->SubType) < 0)
  367.         {
  368.             yerror(lexIdx,  EWARN_RETURN_MISMATCH, TypeToProtoStr(tn->SubType, 0));
  369.             yerror(olexIdx, EWARN_DOES_NOT_MATCH,  TypeToProtoStr(to->SubType, 0));
  370.         }
  371.         if (to->Args > 0 && tn->Args < 0)
  372.         {
  373.             yerror(lexIdx, (ProtoOnlyOpt) ? EERROR_NON_PROTOTYPE
  374.                                           : EWARN_NON_PROTOTYPE);
  375.         break;
  376.         }
  377.         if (to->Args < 0 || tn->Args < 0)
  378.         return(0);
  379.  
  380.             /*
  381.              *  prototyped
  382.              */
  383.  
  384.             if (to->Args == tn->Args)
  385.             {
  386.                 short i;
  387.  
  388.                 for (i = 0; i < tn->Args; ++i) {
  389.                     Var *v1 = tn->Vars[i];
  390.                     Var *v2 = to->Vars[i];
  391.  
  392.                     if (CompareTypes(olexIdx, lexIdx, v1->Type, v2->Type) < 0) {
  393.                         yerror(lexIdx, EERROR_ARGUMENT_MISMATCH,
  394.                                        i + 1, TypeToProtoStr(v1->Type, 0));
  395.                         yerror(olexIdx, EWARN_DOES_NOT_MATCH,
  396.                                        TypeToProtoStr(v2->Type, 0));
  397.                         break;
  398.                     }
  399.                     if ((v1->RegFlags ^ v2->RegFlags) & (RF_REGISTER|RF_REGMASK)) {
  400.                         yerror(lexIdx, EERROR_REGISTER_MISMATCH, i + 1);
  401.                         break;
  402.                     }
  403.                 }
  404.                 if (i == tn->Args)
  405.                     return(0);
  406.             }
  407.             else
  408.             {
  409.                 yerror(lexIdx, EERROR_ARGUMENT_COUNT);
  410.             }
  411.         break;
  412.     case TID_STRUCT:
  413.     case TID_UNION:
  414.     case TID_BITFIELD:
  415.         if (tn->Id == to->Id && tn->Args == to->Args && tn->Vars == to->Vars)
  416.         return(0);
  417.         yerror(lexIdx, EERROR_INCOMPATIBLE_STRUCTURE, TypeToProtoStr(tn, 0));
  418.             yerror(olexIdx, EWARN_DOES_NOT_MATCH, TypeToProtoStr(to, 0));
  419.         break;
  420.     }
  421.     break;
  422.     }
  423.     if (tn != to)
  424.     return(-1);
  425.     return(0);
  426. }
  427.  
  428.